package com.netcracker.educenter.filestorage.servlets.security.registration;

import com.netcracker.educenter.filestorage.configurator.Configurator;
import com.netcracker.educenter.filestorage.datasource.dao.UserAccess;
import com.netcracker.educenter.filestorage.datasource.dao.user.UserDAO;
import com.netcracker.educenter.filestorage.datasource.entity.User;
import org.apache.log4j.Logger;

import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

@WebServlet(urlPatterns = "/Registration")
public class RegistrationServlet extends HttpServlet {

    private static final Logger log = Logger.getLogger(RegistrationServlet.class.getName());

    private static final String PERSONAL_PAGE_URL = Configurator.getConfigurator().getFileslistPageUrl();
    private static final String REGISTRATION_PAGE_URL = Configurator.getConfigurator().getRegistrationPageUrl();

    private static final Pattern LOGIN_PATTERN = Pattern.compile("^[a-zA-Z][\\w-]{2,15}$");
    private static final Pattern PASSWORD_PATTERN = Pattern.compile("^[a-zA-Z0-9!@#\\$%\\^&\\(\\)-_\\+=\\?]{8,20}$");

    private static final String INVALID_LOGIN_MESSAGE = "Логин должен содержать от 3 до 16 символов. "
            + "Можно использовать латинский алфавит, цифры, символы дефиса и подчёркивания. "
            + "Логин обязательно должен начинаться с буквы.";

    private static final String INVALID_PASSWORD_MESSAGE = "Пароль должен содержать от 8 до 20 символов."
            + " Можно использовать буквы латинского алфавита, цифры, символы "
            + "!, @, #, $, %, ^, &, ), (, -, _, +, =, ?.";
    private static final String REGISTRATION_ERROR = "registration_error";

    @Override
    public void service(HttpServletRequest request, HttpServletResponse response) {

        String nextPage = REGISTRATION_PAGE_URL;
        String login = request.getParameter("username");
        String password = request.getParameter("password1");

        HttpSession session = request.getSession();

        if (password == null || password.trim().isEmpty() || login == null || login.trim().isEmpty()) {

            session.setAttribute(REGISTRATION_ERROR, "Нужно заполнить все поля!");

        } else if (!password.equals(request.getParameter("password2"))) {

            session.setAttribute(REGISTRATION_ERROR, "Пароли не совпадают!");

        } else {
            Matcher matcher = LOGIN_PATTERN.matcher(login);
            if (!matcher.matches()) {

                session.setAttribute(REGISTRATION_ERROR, INVALID_LOGIN_MESSAGE);

            } else {
                UserAccess userAccess = new UserDAO();
                if (userAccess.userExist(login)) {

                    session.setAttribute(REGISTRATION_ERROR, "Пользователь с таким именем уже зарегистрирован!");

                } else {

                    matcher = PASSWORD_PATTERN.matcher(password);
                    if (!matcher.matches()) {

                        session.setAttribute(REGISTRATION_ERROR, INVALID_PASSWORD_MESSAGE);

                    } else {
                        // Registration:
                        User user = new User();
                        user.setLogin(login);
                        user.setPassword(password);

                        // Add user's data to database and create personal directory on disk
                        if (userAccess.add(user) && createUsersDirectory(login)) {

                            session.setAttribute(REGISTRATION_ERROR, null);
                            session.setAttribute("authorized_user", login);
                            nextPage = PERSONAL_PAGE_URL;

                        } else {

                            session.setAttribute(REGISTRATION_ERROR, "Ошибка на сервере. Попробуйте позже.");
                            log.error(String.format("Cannot add user %s", login));
                        }
                    }
                }
            }
        }

        try {
            response.sendRedirect(request.getContextPath() + nextPage);
        } catch (Exception e) {
            log.error("cannot go to page", e);
        }
    }

    private boolean createUsersDirectory(String name) {

        Path path = Paths.get(Configurator.getConfigurator().getPath()).resolve(name);
        try {
            Files.createDirectory(path);
        } catch (IOException e) {
            log.error(String.format("Cannot create directory for user %s.", name), e);
            return false;
        }
        return true;
    }
}
